package com.polaris.live.utils

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.text.style.ReplacementSpan
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.lifecycle.LifecycleCoroutineScope
import com.blankj.utilcode.util.ColorUtils
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.SpanUtils
import com.blankj.utilcode.util.SpanUtils.ALIGN_CENTER
import com.blankj.utilcode.util.StringUtils
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CircleCrop
import com.hjq.language.MultiLanguages
import com.polaris.live.R
import com.polaris.live.common.cacha.CacheUtil
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.constant.AppConst
import com.polaris.live.common.constant.CommonConst
import com.polaris.live.common.constant.PagConst
import com.polaris.live.common.ext.autoDp
import com.polaris.live.common.ext.dp
import com.polaris.live.common.util.AppCodeUtils
import com.polaris.live.common.util.JsonUtils
import com.polaris.live.im.sfs.bean.live.SendLiveMessage
import com.polaris.live.im.sfs.bean.live.ext.MessageUserExtBean
import com.polaris.live.im.sfs.bean.live.payload.AnimationLayersVo
import com.polaris.live.manager.AssetsConfigManager
import com.polaris.live.manager.LiveStateManager
import com.polaris.live.resp.back_resp.FillGameNumericResp
import com.polaris.live.ui.game.GameUtils
import com.polaris.live.ui.party.PartyUserStateUtil
import com.polaris.live.utils.image.ImageUtils
import com.polaris.live.utils.image.ImageUtils.loadImage
import org.libpag.PAGFile
import org.libpag.PAGImage
import org.libpag.PAGImageView
import java.nio.ByteBuffer
import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.UUID

/**
 * 常用的工具类
 *
 * @author Created by 半仙 on 2023/9/4/004 15:50
 */
object CommonUtils {

    //uuid会自动生成-这个符号需要给他去掉
    fun uuid(): String {
        return UUID.randomUUID().toString().replace("-", "")
    }

    //通过国家code获取国家名字
    fun getCountryName(countryCode: String): String? {
        val locale = Locale(MultiLanguages.getAppLanguage().language, countryCode)
        return locale.getDisplayCountry(locale)
    }

    fun getLanguage(languageCode: String): String {
        val locale = Locale(languageCode)
        return when (locale.getDisplayName(locale)) {
            "zh-cn" -> {
                "简体中文"
            }

            "zh-tw" -> {
                "繁体中文"
            }

            else -> {
                locale.getDisplayName(locale)
            }
        }
    }

    fun getLanguageNameFromLocaleCode(languageCode: String): String {
        //那种方式都可以
//        val forLanguageTag = Locale.forLanguageTag("zh-CN")
//        val display = forLanguageTag.getDisplayLanguage(Locale.forLanguageTag(languageCode))
        return Locale.forLanguageTag(languageCode).displayName
    }

    fun getLanguageNameFromCode(languageCode: String): String {
        val languageList = AssetsConfigManager.fetchLanguage()
        if (languageList != null) {
            val language = languageList.find { it.language == languageCode }
            if (language != null) {
                return language.localName
            }
        }
        return Locale(languageCode).displayName
    }

    //获取年龄
    fun getAge(birthday: Long): Int {
        val serviceTime = CacheUtil.getServerTime()

        val serverDate = Date(serviceTime)
        val birthdayDate = Date(birthday)

        val serverCalendar = Calendar.getInstance()
        serverCalendar.time = serverDate

        val birthdayCalendar = Calendar.getInstance()
        birthdayCalendar.time = birthdayDate

        var age = serverCalendar.get(Calendar.YEAR) - birthdayCalendar.get(Calendar.YEAR)

        // 检查是否已过生日
        if (serverCalendar.get(Calendar.MONTH) < birthdayCalendar.get(Calendar.MONTH) ||
            (serverCalendar.get(Calendar.MONTH) == birthdayCalendar.get(Calendar.MONTH) &&
                    serverCalendar.get(Calendar.DAY_OF_MONTH) < birthdayCalendar.get(Calendar.DAY_OF_MONTH))
        ) {
            age--
        }

        return age
    }

    fun byteBufferToByteArray(bytes: ByteBuffer): ByteArray {
        val len = bytes.limit() - bytes.position()
        val bytes1 = ByteArray(len)
        bytes.get(bytes1)
        return bytes1
    }

    //判断男女
    fun isMan(sex: Int): Boolean = sex == AppConst.UserSex.MAN || AppConst.UserSex.NONE == sex

    //判断是否为安全用户
    fun isSafeUser(safeLevel: Int?, safeType: Int?): Boolean {

        if (safeLevel == null || safeType == null) return false

        return safeLevel > 0 && safeType == CommonConst.SafeLevel.NORMAL
    }

    //判断是否有当前用户是否有封面
    fun isHavaCover(): Boolean {
        return UserManager.getUser().coverPhoto != null && UserManager.getUser().coverPhoto?.hasCoverPhoto == true
    }

    //直播公屏拼接
    suspend fun setSpanData(
        textView: TextView,
        item: SendLiveMessage,
        context: Context,
    ): SpanUtils {
        val span = SpanUtils()

        var ext: MessageUserExtBean? = null
        item.ext?.let {
            ext = it as MessageUserExtBean
        }
        val colorId =
            if (ext?.user?.userId == UserManager.getUser().userId) {
                ColorUtils.getColor(R.color.d2ff4b)
            } else {
                RichCharmImgUtil.serColor2HexColor(ext?.user?.nicknameColor)
                    ?: ColorUtils.getColor(R.color.color_fff1b1)
            }

        val (level, levelImg, levelColor) = resolveRichCharmLevel(ext?.user?.sex, ext?.user?.richs, ext?.user?.charms)

        val levelImage = loadImage(context, levelImg, 16, 16)
        ext?.user?.label?.let {
            val label = JsonUtils.fromJson<List<String>>(it)
            if (label?.isNotEmpty() == true) {
                label.forEach {
                    val imageData = splitUrl(it)
                    val bitmap = ImageUtils.loadNetImageBitmapNoTransform(
                        context,
                        ImageUtils.imgPath(imageData.first),
                        imageData.second.toFloat(),
                        imageData.third.toFloat()
                    )
                    if (bitmap != null) {
                        span.append(" ")
                        span.appendImage(bitmap, ALIGN_CENTER)
                    }
                }
            }
        }

        val nickname = if (ext?.user?.userId == UserManager.getUser().userId) {
            StringUtils.getString(com.polaris.live.translation.R.string.you)
        } else {
            "${ext?.user?.nickname?.trim()}"
        }
        val lineHeight = textView.lineHeight
        span.append(" $nickname ")
            .setLineHeight(2 * lineHeight, ALIGN_CENTER)
            .setForegroundColor(colorId)

        if (levelImage != null) {
            span.appendImage(levelImage, ALIGN_CENTER)
                .append("$level")
                .setLineHeight(2 * lineHeight, ALIGN_CENTER)
                .setSpans(createCustomSpan(levelColor))
                .setFontSize(11, true)
                .setBold()
        }

        return span
    }

    private fun splitLabelPath(url: String): Pair<String, Map<String, String>>? {
        val regex = Regex("""([^?]+)\?(.+)""")
        val matchResult = regex.matchEntire(url) ?: return null

        val path = matchResult.groupValues.getOrNull(1) ?: return null
        val query = matchResult.groupValues.getOrNull(2) ?: return null

        val queryParameters = query.split("&")
            .map { it.split("=") }
            .associateBy({ it[0] }, { it.getOrNull(1) ?: "" })

        return Pair(path, queryParameters)
    }

    private fun splitUrl(url: String): Triple<String, Int, Int> {
        val splitPath = splitLabelPath(url) ?: return Triple("", 0, 0)

        val width = ((splitPath.second["width"]?.toIntOrNull() ?: 0) / 2)
        val height = ((splitPath.second["height"]?.toIntOrNull() ?: 0) / 2)

        return Triple(splitPath.first, width, height)
    }

    fun splitLabelUrl(imageView: ImageView, url: String): String {
        val splitPath = splitLabelPath(url) ?: return ""

        val width = ((splitPath.second["width"]?.toIntOrNull() ?: 0) / 2).dp
        val height = ((splitPath.second["height"]?.toIntOrNull() ?: 0) / 2).dp

        val layoutParams = LinearLayout.LayoutParams(width, height).apply {
            marginEnd = 4.autoDp
        }
        imageView.layoutParams = layoutParams

        return splitPath.first
    }

    fun setNumberMedal(
        lifecycleScope: LifecycleCoroutineScope?,
        numberMedal: String?,
        pagImageView: PAGImageView,
        imageView: ImageView,
    ) {
        if (numberMedal?.isNotEmpty() == true) {
            if (numberMedal.contains(PagConst.PAG)) {
                pagImageView.visibility = View.VISIBLE
                imageView.visibility = View.GONE
                if (lifecycleScope != null) {
                    pagImageView.playAsync(lifecycleScope, numberMedal)
                }
            } else {
                pagImageView.visibility = View.GONE
                imageView.visibility = View.VISIBLE
                Glide.with(imageView.context).load(ImageUtils.imgPath(numberMedal))
                    .transform(CircleCrop())
                    .into(imageView)
            }
        } else {
            pagImageView.visibility = View.GONE
            imageView.visibility = View.GONE
        }
    }

    //TODO 后面优化 后续考虑用对象池来优化这里
    private fun createCustomSpan(strokeColor: Int): ReplacementSpan {
        return object : ReplacementSpan() {
            override fun getSize(
                paint: Paint,
                text: CharSequence?,
                start: Int,
                end: Int,
                fm: Paint.FontMetricsInt?,
            ): Int {
                return paint.measureText(text, start, end).toInt()
            }

            override fun draw(
                canvas: Canvas,
                text: CharSequence,
                start: Int,
                end: Int,
                x: Float,
                top: Int,
                y: Int,
                bottom: Int,
                paint: Paint,
            ) {
                val originalColor = paint.color
                val originalStyle = paint.style
                val originalWidth = paint.strokeWidth

                //设置实心颜色
                paint.color = ColorUtils.getColor(R.color.white)//实心颜色
                paint.style = Paint.Style.FILL//实心样式
                paint.strokeWidth = 2f //描边宽度
                paint.isAntiAlias = true//抗锯齿

                canvas.drawText(text, start, end, x - 1.autoDp.arReverse, (y + 1.autoDp).toFloat(), paint)

                //重新设置颜色和样式，画描边的文字
                paint.color = ColorUtils.getColor(strokeColor) // 描边颜色
                paint.style = Paint.Style.STROKE // 描边样式
                paint.strokeWidth = 1f // 描边宽度

                canvas.drawText(text, start, end, x - 1.autoDp.arReverse, (y + 1.autoDp).toFloat(), paint)

                paint.color = originalColor
                paint.style = originalStyle
                paint.strokeWidth = originalWidth
            }
        }
    }

    private fun resolveRichCharmLevel(sex: Int?, richs: Long?, charms: Long?): Triple<Int, Int?, Int> {
        val isMan = sex?.let { isMan(it) }
        val level = if (isMan == true) {
            RichCharmImgUtil.getLiveRichImg(richs ?: 0)
        } else {
            RichCharmImgUtil.getLiveCharmImg(charms ?: 0)
        }

        return level

    }

    val Int.arReverse: Int
        get() {
            return if (AppCodeUtils.isAR()) {
                -this
            } else {
                this
            }
        }

    //判断是否
    fun Int?.toBoolean() = this == AppConst.YES
    fun Long?.toBoolean() = this == AppConst.YESLONG

    //根据奖励类型返回对应图标
    fun invokeGameRewardIcon(rewardsType: Int): Int {
        return when (rewardsType) {
            CommonConst.PartyAssetType.COIN -> R.drawable.game_reward_type_beans
            CommonConst.PartyAssetType.DIAMOND -> R.drawable.game_reward_type_diamond
            CommonConst.PartyAssetType.FREE -> R.drawable.game_reward_type_free
            else -> {
                0
            }
        }
    }

    //根据奖励类型返回对应图标
    fun invokeGameRewardIcon2(rewardsType: Int): Int {
        return when (rewardsType) {
            CommonConst.PartyAssetType.COIN -> R.drawable.ic_game_beans
            CommonConst.PartyAssetType.DIAMOND -> R.drawable.ic_diamond1
            CommonConst.PartyAssetType.FREE -> R.drawable.party_game_free
            else -> {
                0
            }
        }
    }

    fun invokeGameRewardRoundIcon(rewardsType: Int): Int {
        return when (rewardsType) {
            CommonConst.PartyAssetType.COIN -> R.drawable.ic_game_beans
            CommonConst.PartyAssetType.DIAMOND -> R.drawable.ic_diamond1
            else -> 0
        }
    }

    fun invokeGameHomeRoundIcon(rewardsType: Int): Int {
        return when (rewardsType) {
            CommonConst.PartyAssetType.COIN -> R.drawable.other_game_reward_game_beans
            CommonConst.PartyAssetType.DIAMOND -> R.drawable.ic_diamond1
            else -> 0
        }
    }

    const val GMAIL_SUFFIX = "@gmail.com"

    /**
     * 处理gmail
     */
    fun resolveGmail(emailPrefix: String?): String? {
        if (emailPrefix == null) {
            return null
        } else if (emailPrefix.endsWith(GMAIL_SUFFIX)) {
            return emailPrefix.lowercase()
        } else if (emailPrefix.contains("@")) {
            return null
        } else if (emailPrefix.isBlank()) {
            return null
        }

        return emailPrefix.lowercase() + GMAIL_SUFFIX
    }

    /**
     * 主播,打电话,游戏中,上麦禁止
     */
    fun canKeepOn(onKeepOn: () -> Unit, onNotKeepOn: (() -> Unit)? = null) {
        if (LiveStateManager.isCalling()
            || LiveStateManager.isLiving()
            || PartyUserStateUtil.master
            || GameUtils.gameRun
            || PartyUserStateUtil.inTheGame
            || PartyUserStateUtil.inTheGameSeat
            || PartyUserStateUtil.inTheMaiSeat
        ) {
            onNotKeepOn?.invoke()
        } else {
            onKeepOn.invoke()
        }
    }

    /**
     * 主页ext解析数值游戏
     */
    fun extGameDealWith(ext: Map<String, Any>?, list: List<Any>, isRemove3: Boolean = false): List<Any> {
        val gameList = mutableListOf<FillGameNumericResp>()

        ext?.get("game")?.let { game ->
            val gameMapList = (game as? List<Map<String, Any>>) ?: return@let
            gameMapList.forEach { map ->
                val bean = GsonUtils.fromJson(GsonUtils.toJson(map) ?: "", FillGameNumericResp::class.java)
                gameList.add(bean)
            }
        }
        val tempList = list.toMutableList()
        gameList.forEach { game ->
            if (isRemove3) {
                if (game.index > 3) {
                    val targetIndex = (game.index - 3).coerceAtMost(tempList.size) // 确保索引不超出范围
                    tempList.add(targetIndex, game.game)
                }
            } else {
                val targetIndex = game.index.coerceAtMost(tempList.size) // 确保索引不超出范围
                tempList.add(targetIndex, game.game)
            }
        }

        return tempList
    }

    //pag替换
    suspend fun pagReplace(context: Context, pagFile: PAGFile, layers: AnimationLayersVo? = null) {
        if (layers != null) {
            val texts = layers.text
            if (texts?.isNotEmpty() == true) {
                texts.forEach {
                    val textData = pagFile.getTextData(it.index)
                    textData.text = it.value
                    pagFile.replaceText(it.index, textData)
                }
            }
            val images = layers.image
            if (images?.isNotEmpty() == true) {
                images.forEach {
                    val loadNetImageBitmap = if (it.rounded == false) {
                        ImageUtils.loadNetImageBitmapNoTransform(context, it.value)
                    } else {
                        ImageUtils.loadNetImageBitmap(context, it.value)
                    }
                    val pagImage = PAGImage.FromBitmap(loadNetImageBitmap)
                    pagFile.replaceImage(it.index, pagImage)
                }
            }
        }
    }

    fun isMiddleEast(region: Int?) = region == CommonConst.Region.MENA
}